package com.prime;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class RightPrimeChecker implements CanCheckIfPrime {

	private static final WrongIfPrimeChecker delegate = new WrongIfPrimeChecker();
	private static final Map<Integer, FutureTask<Boolean>> tasks = new ConcurrentHashMap<>();
	
	/**
	 * Thread safe!
	 * */
	@Override
	public boolean isPrime(final int number) throws ExecutionException, InterruptedException {
		try {
			FutureTask<Boolean> task = tasks.get(number);
			if (task == null) {
				FutureTask<Boolean> newTask = new FutureTask<>(
						() -> delegate.isPrime(number)
				);
				FutureTask<Boolean> oldTask = tasks.putIfAbsent(number, newTask);
				if (oldTask == null) {
					newTask.run();
					task = newTask;
				} else {
					task = oldTask;
				}
			}
			return task.get();
		} finally {
			tasks.remove(number);
		}
	}



	public static void main(String[] args) {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				CanCheckIfPrime checker = new RightPrimeChecker();
				for(int i = Integer.MAX_VALUE; i > 2; i --){
					try {
						checker.isPrime(i);
					} catch (ExecutionException | InterruptedException e) {
						System.err.println("Calc was interrupted (canceled)" + e.getMessage());
					}
				}
			}
		};
		Thread t1 = new Thread(r), t2 = new Thread(r);
		t1.start();
		t2.start();
	}
}
